package collection

import (
	"iter"
	"sync"

	"gitee.com/gousing/helper/jsoner"
)

// MapSetSync 泛型化集合, 便捷的SET集合类型数据结构(有锁, 并发安全)
//   - 使用sync.RWMutex 控制并发场景
//   - 适用于读多写少场景
type MapSetSync[T comparable] struct {
	data map[T]struct{}
	mu   sync.RWMutex
}

// NewMapSetSync 创建一个新的MapSetSync
func NewMapSetSync[T comparable](size ...int) *MapSetSync[T] {
	if len(size) > 0 {
		return &MapSetSync[T]{make(map[T]struct{}, size[0]), sync.RWMutex{}}
	}
	return &MapSetSync[T]{make(map[T]struct{}), sync.RWMutex{}}
}

// Push 添加元素
//   - 返回值为添加成功的个数
func (s *MapSetSync[T]) Push(vals ...T) int {
	if len(vals) == 0 {
		return 0
	}
	s.mu.Lock()
	defer s.mu.Unlock()
	prevLen := len(s.data)
	for _, v := range vals {
		s.data[v] = struct{}{}
	}
	return len(s.data) - prevLen
}

// Has 快速判断单个元素是否存在
func (s *MapSetSync[T]) Has(val T) (exists bool) {
	s.mu.RLock()
	defer s.mu.RUnlock()
	_, exists = s.data[val]
	return
}

// Contains 快速判断多个元素是否全部都存在
func (s *MapSetSync[T]) Contains(vals ...T) (exists bool) {
	s.mu.RLock()
	defer s.mu.RUnlock()
	for _, v := range vals {
		if _, ok := s.data[v]; !ok {
			return false
		}
	}
	return true
}

// SomeContains 快速判断是否存在指定多个元素中的某一个
func (s *MapSetSync[T]) SomeContains(vals ...T) (exists bool) {
	s.mu.RLock()
	defer s.mu.RUnlock()
	for _, v := range vals {
		if _, ok := s.data[v]; ok {
			return true
		}
	}
	return false
}

// Equal 判断两个集合是否相等
//   - 如果参数集合与当前集合的容量和全部元素是相同的，那么会被然认为是相同的
//   - 不考虑集合元素的顺序
func (s *MapSetSync[T]) Equal(other *MapSetSync[T]) bool {
	s.mu.RLock()
	defer s.mu.RUnlock()
	if len(s.data) != other.Size() {
		return false
	}
	for key := range s.data {
		if !other.Has(key) {
			return false
		}
	}
	return true
}

// Intersect 求当前集合与指定集合的交集
//   - 如果参数集合与当前集合的容量和全部元素是相同的，那么会被然认为是相同的，无需考虑元素的顺序
func (s *MapSetSync[T]) Intersect(other *MapSetSync[T]) *MapSetSync[T] {
	s.mu.RLock()
	defer s.mu.RUnlock()
	newMap := NewMapSetSync[T]()
	if len(s.data) < other.Size() {
		for key := range s.data {
			if other.Has(key) {
				newMap.data[key] = struct{}{}
			}
		}
	} else {
		for key := range other.Iter() {
			if s.Has(key) {
				newMap.data[key] = struct{}{}
			}
		}
	}
	return newMap
}

// Difference 求当前set集合与指定other集合的差集
//   - 并返回一个差集，该差集包括了set集合中部分或全部值，条件为不在指定other集合中的值。
func (s *MapSetSync[T]) Difference(other *MapSetSync[T]) *MapSetSync[T] {
	s.mu.RLock()
	defer s.mu.RUnlock()
	newMap := NewMapSetSync[T]()
	for key := range s.data {
		if !other.Has(key) {
			newMap.data[key] = struct{}{}
		}
	}
	return newMap
}

// Union 求当前集合与指定集合的并集
//   - 不考虑元素的顺序，元素顺序是随机的
func (s *MapSetSync[T]) Union(other *MapSetSync[T]) *MapSetSync[T] {
	s.mu.RLock()
	defer s.mu.RUnlock()
	newMap := s.Clone()
	for key := range other.Iter() {
		newMap.data[key] = struct{}{}
	}
	return newMap
}

// IsSubset 判断当前set集合是否为参数other集合的子集（包含，允许相等）
func (s *MapSetSync[T]) IsSubset(other *MapSetSync[T]) bool {
	s.mu.RLock()
	defer s.mu.RUnlock()
	if len(s.data) > other.Size() {
		return false
	}
	for key := range s.data {
		if !other.Has(key) {
			return false
		}
	}
	return true
}

// IsSuperset 判断参数other集合是否为当前set集合的子集（包含，允许相等）
func (s *MapSetSync[T]) IsSuperset(other *MapSetSync[T]) bool {
	return other.IsSubset(s)
}

// IsProperSubset 判断当前set集合是否为参数other集合的真子集（包含但不相等）
func (s *MapSetSync[T]) IsProperSubset(other *MapSetSync[T]) bool {
	return s.IsSubset(other) && s.Size() < other.Size()
}

// IsProperSuperset 判断参数other集合是否为当前set集合的真子集（包含但不相等）
func (s *MapSetSync[T]) IsProperSuperset(other *MapSetSync[T]) bool {
	return s.IsSuperset(other) && s.Size() > other.Size()
}

// Remove 删除元素
func (s *MapSetSync[T]) Remove(val T) (exists bool) {
	s.mu.Lock()
	defer s.mu.Unlock()
	delete(s.data, val)
	return
}

// Clear 清空集合
func (s *MapSetSync[T]) Clear() {
	s.mu.Lock()
	defer s.mu.Unlock()
	for key := range s.data {
		delete(s.data, key)
	}
}

// IsEmpty 判断集合是否为空
func (s *MapSetSync[T]) IsEmpty() bool {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return len(s.data) == 0
}

// Size 获取集合元素个数
func (s *MapSetSync[T]) Size() int {
	s.mu.RLock()
	defer s.mu.RUnlock()
	return len(s.data)
}

// Iter 集合元素迭代器
//   - 迭代器返回的元素顺序和添加的顺序不一致
//   - for v:=range s.Iter(){}
func (s *MapSetSync[T]) Iter() iter.Seq[T] {
	return func(yield func(val T) bool) {
		s.mu.RLock()
		defer s.mu.RUnlock()
		for v := range s.data {
			if !yield(v) {
				return
			}
		}
	}
}

// Values 获取集合元素切片对象
func (s *MapSetSync[T]) Values() (values []T) {
	s.mu.RLock()
	values = make([]T, 0, len(s.data))
	for elem := range s.data {
		values = append(values, elem)
	}
	s.mu.RUnlock()
	return values
}

// Clone 复制一个集合
func (s *MapSetSync[T]) Clone() *MapSetSync[T] {
	s.mu.RLock()
	newMap := &MapSetSync[T]{
		data: make(map[T]struct{}, len(s.data)),
		mu:   sync.RWMutex{},
	}
	for key := range s.data {
		newMap.data[key] = struct{}{}
	}
	s.mu.RUnlock()
	return newMap
}

// MarshalJSON 序列化集合接口
func (s *MapSetSync[T]) MarshalJSON() ([]byte, error) {
	s.mu.RLock()
	defer s.mu.RUnlock()
	items := make([]T, 0, s.Size())
	for elem := range s.data {
		items = append(items, elem)
	}
	return jsoner.Marshal(items)
}

// UnmarshalJSON 反序列化集合接口
func (s *MapSetSync[T]) UnmarshalJSON(data []byte) error {
	var items []T
	err := jsoner.Unmarshal(data, &items)
	if err != nil {
		return err
	}
	s.mu.Lock()
	defer s.mu.Unlock()
	for key := range s.data {
		delete(s.data, key)
	}
	if len(items) == 0 {
		return nil
	}
	for _, v := range items {
		s.data[v] = struct{}{}
	}
	return nil
}
